package com.itheima.Spring;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SpringApplicationContext {
    //随便起个名
    private String nameItAnything;
    //在SpringApplicationContext类中声明一个Map类型的全局变量，用来模拟Spring的容器
    private Map<String, Object> map = new HashMap<String, Object>();


    public SpringApplicationContext(String nameItAnything) {
        this.nameItAnything = nameItAnything;
        //在SpringApplicationContext类中提供一个方法，用来解析beans.xml配置文件
        randomMethodXml();
    }

    private void randomMethodXml() {
        try {
            //1.获取sax 解析器对象
            SAXReader sr = new SAXReader();
            //2.根据文件名获取文件的输入流对象
            InputStream is = SpringApplicationContext.class.getClassLoader().getResourceAsStream(nameItAnything);
            //3.获取文件的 Document 对象
            Document documentXml = sr.read(is);
            //4.获取根元素 （beans）
            Element rootElement = documentXml.getRootElement();
            //5.获取根元素下面的名字为 bean 的子元素  （bean）
            List<Element> beanList = rootElement.elements("bean");
            //遍历获取所有子元素
            if (beanList != null && beanList.size() > 0) {
                for (Element bean : beanList) {
                    //6.获取 bean 元素的 id 和 class
                    String id = bean.attributeValue("id");
                    String clazz = bean.attributeValue("class");
                    //7.使用反射加载类对象
                    Class<?> clazzs = Class.forName(clazz);
                    Object o = clazzs.getDeclaredConstructor().newInstance();
                    //8.获取 bean 标签下的所有 property 标签
                    List<Element> propertys = bean.elements("property");
                    if (propertys != null && propertys.size() > 0) {
                        for (Element proElement : propertys) {
                            //9. //6.获取 property 元素的 username 和 value
                            String name = proElement.attributeValue("name");
                            //10.获取name 标签的 值
                            Field clazzsDeclaredField = clazzs.getDeclaredField(name);
                            clazzsDeclaredField.setAccessible(true);
                            //获取 value 标签的 值
                            String value = proElement.attributeValue("value");
                            if (value != null){
                                clazzsDeclaredField.set(o, value);
                            }
                        }
                    }
                    //11.将获取的 bean 对象存到 map 集合中
                    map.put(id, o);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public <T> T getBean(String userService) {

        return (T)map.get(userService);
    }
}





